home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////////
- // FILENAME: eTFileLink.m
- // SUMMARY: Implementation of file components for eText documents
- // SUPERCLASS: eTImage
- // INTERFACE: None
- // PROTOCOLS: <Annotation,HTMDSupport,ASCIISupport,LaTeXSupport,Tool,
- // InspectableTarget>
- // AUTHOR: Rohit Khare
- // COPYRIGHT: (c) 1994 California Institure of Technology, eText Project
- ///////////////////////////////////////////////////////////////////////////////
- // DESCRIPTION
- // Does its job by an eTComponent and execString.
- ///////////////////////////////////////////////////////////////////////////////
- // HISTORY
- // 10/30/94: Modified to support <InspectableTarget>
- // 08/06/94: Added symbolic linking support.
- // 07/21/94: Created. First actual implementation.
- ///////////////////////////////////////////////////////////////////////////////
-
- #import "eTFileLink.h"
- #define _eTFileLinkPR1 10
- #define _eTFileLinkVERSION 20
-
- @implementation eTFileLink
- // id etFileComponent;
- // char *execString;
- // BOOL isExecEnabled;
- // BOOL useSymlink;
-
- - setSymlink:(BOOL)newState
- {useSymlink = newState; return self;}
- - setExecEnabled:(BOOL)newState
- {isExecEnabled = newState; return self;}
- - (BOOL)useSymlink
- {return useSymlink;}
- - (BOOL)isExecEnabled
- {return isExecEnabled;}
- - (const char *)componentName
- {return ((etFileComponent) ? [etFileComponent componentName] : NXUniqueString(""));}
- - (BOOL)isLinked
- {return ((etFileComponent) ? [etFileComponent isLinked] : NO);}
- - (const char *)execString
- {return execString;}
- - setExecString:(const char *) newString
- {
- if (!newString) return self;
- if ((!(*execString)) && *newString)
- isExecEnabled = YES;
- execString = realloc(execString, (strlen(newString)+1)*sizeof(char));
- strcpy(execString, newString);
- return self;
- }
- ////////////////////////////
- + toolAwake:theApp
- {
- [theApp registerAnnotation: [eTFileLink class]
- name: "eTFileLink"
- RTFDirective: "eTFileLink"
- menuLabel: NULL
- menuKey: '\0'
- menuIcon: (NXImage *) nil];
- [theApp registerType:NXCreateFileContentsPboardType(ANY_TYPE) for:[eTFileLink class]];
- [eTRTFDFileLink toolAwake:theApp]; // "delegate chain"
- return self;
- }
-
- - init
- {
- [super init];
-
- [self setUsesButtonStyle:NO];
- [self setDraggable:YES];
- isExecEnabled = NO;
- useSymlink = NO;
- if (!execString) {
- execString = malloc(2 * sizeof(char));
- execString[0] = '\0';
- }
- return self;
- }
-
- - free
- {
- free(execString);
- etFileComponent = [etFileComponent free];
- return self = [super free];
- }
-
- - _hack:sender
- {
- // this is to prevent deadlock with the Workspace when
- // requesting an icon during a dragging session
-
- // This is hardcoded: all FileLinks are ANY_TYPE; icons are .tiff
- char imgName[MAXPATHLEN];
-
- sprintf(imgName,"%s.tiff",[etFileComponent componentName]);
- [self setImageComponent:[[[eTImageComponent alloc] initInDoc:etDoc linked:NO] useImage:[etFileComponent icon] name:imgName path:NXUniqueString("") shared:NO]];
- [self updateGraphics];
- return self;
- }
- - initFromPboard:thePB inDoc:theDoc linked:(BOOL) linked
- {
- NXAtom types[3];
- char *data;
- int len;
-
- [self init];
- // we prevent super from executing initFromPboard, so we have to:
- etDoc = theDoc;
- theText = [[etDoc docUI] eTextObj]; // consistency checking
- [etDoc registerNotification:self];
-
- types[0] = NXCreateFileContentsPboardType(ANY_TYPE);
- types[1] = NXFilenamePboardType;
- types[2] = [thePB findAvailableTypeFrom:types num:2];
-
- if (!types[2]) return self;
- if (types[2] == NXFilenamePboardType) {
- [thePB readType:NXFilenamePboardType data:&data length:&len];
- if (index(data,'\t')) *(index(data,'\t'))=0;
- etFileComponent = [[eTComponent alloc] initInDoc:etDoc
- linked:linked];
- [etFileComponent readComponentFromPath:data];
- [self perform:@selector(_hack:) with:nil afterDelay:0 cancelPrevious:NO];
- [thePB deallocatePasteboardData:data length:len];
- } else {
- NXLogError("%s got fcontents without fnamepboard! %s instead.\n",
- [[self class] name], types[2]);
- }
- return self;
- }
- - writeComponentToPath:(NXAtom)path inFormat:(int) theFormat
- {
- if(!etDoc) NXLogError("etDoc is nil at %s %u",__FILE__,__LINE__);
- if (useSymlink)
- [etFileComponent writeComponentToPath:path inFormat:theFormat];
- else
- [etFileComponent linkComponentToPath:path];
- return [super writeComponentToPath:path inFormat:theFormat];
- }
- - addToPboard:pboard
- {
- [etFileComponent addToPboard:pboard];
- return self;
- }
- - readRichText:(NXStream *)stream forView:view
- {
- int i, ver;
- char buf[MAXPATHLEN];
-
- NXScanf(stream, "%d ", &ver);
- if ((ver != _eTFileLinkVERSION) && (ver != _eTFileLinkPR1)) {
- // bad version block.
- NXLogError("eTFileLink found unparseable version %d at position %d",
- ver, NXTell(stream));
- return nil;
- }
-
- NXScanf(stream, "%c ", &isExecEnabled);
- isExecEnabled -= 'A';
-
- if (ver == _eTFileLinkVERSION) {
- NXScanf(stream, "%c ", &useSymlink);
- useSymlink -= 'A';
- }
-
- NXScanf(stream, "%d", &i); NXGetc(stream); // space-eater
- if (i) {
- NXRead(stream, buf, i);
- buf[i] = 0;
- [self setExecString:buf];
- NXGetc(stream); // trailing space
- } // if i was zero, we have already advanced to the next non-white bit.
- [super readRichText:stream forView:view];
- NXGetc(stream); // separating space
- etFileComponent = [[[eTComponent alloc] init] readRichText:stream forView:view];
- return self;
- }
-
- - writeRichText:(NXStream *)stream forView:view
- {
- NXPrintf(stream, "%d %c %c %d %s ", _eTFileLinkVERSION,
- isExecEnabled + 'A', useSymlink + 'A', strlen(execString), execString);
- [super writeRichText:stream forView:view];
- NXPutc(stream, ' '); // separate the two visually
- [etFileComponent writeRichText:stream forView:view];
- return self;
- }
-
- - writeASCIIRef:(NXStream *)stream forView:view
- {
- NXPrintf(stream, "See the file %y (last known address:%s)\n\t", [etFileComponent componentName], [etFileComponent currentPath]);
- [super writeASCIIRef:stream forView:view];
- return self;
- }
-
- - writeLaTeX:(NXStream*)stream forView:view
- {
- [super writeLaTeX:stream forView:view];
- [etFileComponent writeLaTeX:stream forView:view
- andClose:(*execString ? YES : NO)];
- if (*execString)
- NXPrintf(stream,
- " Try executing the file with {\\tt %w}.}\n", execString);
- return self;
- }
-
- - writeHTML:(NXStream *)stream forView:view
- {
- [etFileComponent writeHTML:stream forView:view andClose:NO];
- [super writeHTML:stream forView:view]; // icon-buttons.
- if (*execString)
- NXPrintf(stream,
- "(execute this file with <TT>"%v"</TT>)", execString);
- NXPrintf(stream,"</A>");
- return self;
- }
-
- - doubleClick:(NXEvent*)e
- {
- NXAtom fname = [etFileComponent currentPath];
-
- if (*fname && !access(fname, F_OK|R_OK)) {
- //ok, now do we open or use execString?
- if (isExecEnabled && *execString) {
- char cmd[MAXPATHLEN];
- id sPanel;
-
- sprintf(cmd, execString, fname, fname, fname);
- // undocumented hole: extra fnames are passed on the stack
- sPanel = NXGetAlertPanel("eTFileLink",
- "Executing the command \"%s\"",
- NULL, NULL, NULL, cmd);
- [sPanel setFloatingPanel:NO];
- [sPanel setHideOnDeactivate:YES];
- [sPanel orderFront:self];
- NXPing();
- system(cmd);
- if (sPanel) {
- [sPanel orderOut:self];
- NXFreeAlertPanel(sPanel);
- }
- } else {
- // we need to flip the location y coord
- NXPoint pt;
- NXSize sz;
- id img;
-
- pt = e->location;
- img = [etFileComponent icon];
- [theText convertPoint:&pt fromView:nil];
- [img getSize:&sz];
- pt.x -= sz.width/2;
- pt.y += sz.height/2;
- [[Application workspace]
- openFile:fname fromImage: img
- at: &pt inView:theText];
- }
- } else {
- if (*fname)
- NXRunAlertPanel("eTFileLink","Could not access() %s.","OK",NULL,NULL,fname);
- }
- return self;
- }
-
- - inspect:(NXEvent *) e
- {
- [[NXApp inspector] inspect:self];
- return self;
- }
- - (id <Inspectable>) inspectableDelegate {
- return [[eTFileLinkUI new] setAnnotation:self]; }
-
- - drag: (Pasteboard *)draggingPboard image:(NXImage **)proxyImage
- {
- if (! etFileComponent) {
- *proxyImage = nil;
- return nil;
- }
- [etFileComponent writeComponentToPboard:draggingPboard];
- *proxyImage = [etFileComponent icon];
- return self;
- }
- @end